#ifndef WINDOW_HPP
#define WINDOW_HPP

#include "pch.hpp"
#include "libmath.hpp"
#include "log.hpp"

namespace sdl_engine {

class Window {
public:
    class CreateInfo {
    public:
        friend class Window;
        friend class Engine;

        inline CreateInfo& SetTitle(const std::string& title) { title_ = title; return *this; }
        inline CreateInfo& SetPosition(const Point& p) { position_ = p; return *this; }
        inline CreateInfo& SetSize(const Size& s) { size_ = s; return *this; }
        inline CreateInfo& SetOpacity(int opacity) { opacity_ = opacity; return *this; }
        inline CreateInfo& SetFlags(u32 flags) { flags_ = flags; return *this; }
        inline CreateInfo& EnableResize() { flags_ |= SDL_WINDOW_RESIZABLE; return *this; }
        inline CreateInfo& FullScreen() { flags_ |= SDL_WINDOW_FULLSCREEN; return *this; }
        inline CreateInfo& Maximize() { flags_ |= SDL_WINDOW_MAXIMIZED; return *this; }
        inline CreateInfo& Minimize() { flags_ |= SDL_WINDOW_MINIMIZED; return *this; }
        inline CreateInfo& SupportOpenGL() { flags_ |= SDL_WINDOW_OPENGL; return *this; }
        inline CreateInfo& SupportVulkan() { flags_ |= SDL_WINDOW_VULKAN; return *this; }
        inline CreateInfo& SetIcon(const std::string& filename) { iconFilename_ = filename; return *this; }
        inline CreateInfo& NoBorder() { flags_ |= SDL_WINDOW_BORDERLESS; return *this; }

    private:
        std::string title_ = "SDL Engine";
        std::string iconFilename_;
        std::optional<int> opacity_;
        Point position_ = point(SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
        Size size_ = size(480, 320);
        u32 flags_ = SDL_WINDOW_SHOWN;
    };

    Window(const Window::CreateInfo& createInfo);
    Window(const Window&) = delete;
    ~Window();

    Window& operator=(const Window&) = delete;

    inline operator bool() const { return window_; }

    std::string GetTitle() const { return SDL_GetWindowTitle(window_); }
    void SetTitle(const std::string& str) {
        return SDL_SetWindowTitle(window_, str.c_str());
    }

    bool IsMaximum() const {
        return SDL_GetWindowFlags(window_) & SDL_WINDOW_MAXIMIZED;
    }

    bool IsMinimum() const {
        return SDL_GetWindowFlags(window_) & SDL_WINDOW_MINIMIZED;
    }

    void Minimize();
    void Maximize();

    void Hide();
    void Show();

    bool IsFullScreen() const {
        return SDL_GetWindowFlags(window_) & SDL_WINDOW_FULLSCREEN;
    }

    void ToggleFullScreen();

    Size GetSize() const;

    SDL_Window* Raw() { return window_; }

private:
    SDL_Window* window_ = nullptr;
};

}

#endif
